import { cloneObj, guid } from '@/utils/common'
import { ref, onMounted, computed, reactive, nextTick, toRaw } from 'vue'
import { confirmDialog, tips, tipsWarning } from '@/utils/tips'
import { database } from '@/utils/IndexDBWarp/index'

/**
 * 配置
 * @typedef {{
 * title:string;
 * tableName:string;
 * formInitData:object;
 * formRef:import('vue').Ref<import('element-plus').FormInstance>;
 * }} IConfig
 */

/**
 * 表单增删改查
 * @param {IConfig} config 配置
 * @returns
 */
export const useCrudForm = (config) => {
  const dialogVisible = ref(false)
  const formDisabled = ref(false)
  const tableData = ref([])
  const editType = ref('add')
  const store = database.getObjectStore(config.tableName)
  const dialogTitle = computed(() => {
    if (editType.value === 'add') return '新增' + config.title
    if (editType.value === 'update') return '编辑' + config.title
    return config.title
  })

  const initFormData = () => cloneObj(config.formInitData)
  const formData = reactive(initFormData())
  const loading = ref(false)

  const getList = async () => {
    const list = await store.getAll() || []
    // 数据排序
    list.sort((a, b) => a.sort - b.sort)
    tableData.value = list
  }

  onMounted(() => {
    getList()
  })

  /**提交表单 */
  const submitForm = async () => {
    if (!config.formRef.value) return tipsWarning('未获取到表单dom，请绑定ref')
    const valid = () => {
      return new Promise((resolve, reject) => {
        config.formRef.value.validate((valid, fields) => valid ? resolve(valid) : reject(fields))
      })
    }
    await valid()
    if (editType.value == 'add') {
      await store.add({ ...toRaw(formData), createTime: Date.now() })
      tips('新增成功')
    } else {
      await store.update(toRaw(formData))
      tips('修改成功')
    }
    getList()
    dialogVisible.value = false
  }
  /**重置表单 */
  const resetForm = async () => {
    await nextTick()
    if (!config.formRef.value) return tipsWarning('未获取到表单dom，请绑定ref')
    config.formRef.value.resetFields()
    Object.assign(formData, initFormData())
  }

  /**新增 */
  const handleAdd = async () => {
    editType.value = 'add'
    dialogVisible.value = true
    await resetForm()
    formDisabled.value = editType.value == 'look'
  }

  /**复制 */
  const handleCopy = async (row, nameKey = 'name') => {
    await confirmDialog('确定复制一条数据吗？')
    let newRow = cloneObj(toRaw(row))
    newRow[nameKey] = newRow[nameKey] + '-副本'
    await store.add({ ...newRow, id: guid(), createTime: Date.now() })
    getList()
  }

  /**编辑 */
  const handleEdit = async (row) => {
    editType.value = 'update'
    dialogVisible.value = true
    await resetForm()
    const info = await store.getById(row.id)
    Object.assign(formData, info)
    formDisabled.value = editType.value == 'look'
  }

  /**查看 */
  const handleLook = async (row) => {
    editType.value = 'look'
    dialogVisible.value = true
    await resetForm()
    const info = await store.getById(row.id)
    Object.assign(formData, info)
    formDisabled.value = editType.value == 'look'
  }

  /**删除 */
  const handleDelete = async (row) => {
    await confirmDialog('确定删除吗？')
    await store.deleteById(row.id)
    tips('删除成功')
    getList()
  }

  return {
    tableData,
    dialogVisible,
    dialogTitle,
    formDisabled,
    formData,
    loading,
    editType,
    handleAdd,
    handleCopy,
    handleEdit,
    handleLook,
    handleDelete,
    submitForm,
    resetForm
  }
}
